package app;

import app.agent.TargetAgent;
import app.database.CrubUtils;
import app.database.RoundData;
import app.util.algo.DirectTA;
import app.env.Data;
import app.env.Position;
import app.env.ShowGui;
import app.agent.Schedule;
import app.tasks.DetectEmit;
import app.util.AppUtils;
import framework.task.Task;
import framework.task.TaskContainer;
import jade.core.AID;
import jade.core.Profile;
import jade.core.ProfileImpl;
import jade.core.Runtime;
import jade.wrapper.AgentController;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jvnet.substance.SubstanceLookAndFeel;
import org.jvnet.substance.api.SubstanceSkin;
import org.jvnet.substance.skin.AutumnSkin;
import org.jvnet.substance.skin.SubstanceAutumnLookAndFeel;

import javax.swing.*;
import java.util.List;
import java.util.Random;

/**
 * @Name: Launcher
 * @Description:
 * @Author: colfish
 * @Date: 2021/4/4
 * 好好学习，天天向上！
 */
public class Launcher {
    private static Logger logger = LogManager.getLogger(Launcher.class);

    public static void main(String[] args){


        try {
            JFrame.setDefaultLookAndFeelDecorated(true);
            JDialog.setDefaultLookAndFeelDecorated(true);
            UIManager.setLookAndFeel(new SubstanceAutumnLookAndFeel());
            SubstanceSkin skin = new AutumnSkin();
            SubstanceLookAndFeel.setSkin(skin);
        } catch (Exception e) {
            System.err.println("Something went wrong!");
        }


        /* =======================初始化常量 Start====================== */

        // 初始化目标代理的个数
        int targetNums = Data.TARGET_NUMS;
        // 初始化地图网格的高和宽
        int height = Data.MAP_HEIGHT;
        int width = Data.MAP_WIDTH;


        /* =======================初始化常量 End====================== */

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {

                // 设置程序运行的轮数
                Data.ROUND = new CrubUtils().getMaxRound();
                logger.info("程序运行的轮数：" + Data.ROUND);
                // 根据round数获得别的数据
                RoundData roundData = new RoundData();
                if(Data.ROUND > 0)
                    roundData = new CrubUtils().getRoundData(Data.ROUND);

                if(roundData!= null){
                    Data.TARGET_NUMS = roundData.getTargetNum() == null ? 0 : roundData.getTargetNum();
                    Data.SEARCH_NUMS = roundData.getSearchNum() == null ? 0 : roundData.getSearchNum();

                }
                logger.info("上次运行目标代理数目：" + Data.TARGET_NUMS);
                logger.info("上次运行搜救代理数目：" + Data.SEARCH_NUMS);
                // 1. 初始化地图资源
                ShowGui.initGui(height, width);
                ShowGui.updateGui();
            }
        });
    }
    public static void initTargetAgent(){

        Runtime runtime = Runtime.instance();
        // 2. 初始化主容器
        Profile mainConfig = new ProfileImpl("localhost", 8888, null);
        mainConfig.setParameter("gui", "false");
        Data.scheduleContainer = runtime.createMainContainer(mainConfig);
        // 3. 初始化目标代理容器
        Profile targetConfig = new ProfileImpl("localhost", 8888, null);
        Data.targetContainer = runtime.createAgentContainer(targetConfig);
        // 随机数
        Random random = new Random();
        int targetNums = Data.TARGET_NUMS;
        int height = Data.MAP_HEIGHT;
        int width = Data.MAP_WIDTH;
        int range = Data.TARGET_RANGE;
        try {
            // 4. 目标代理容器初始化目标代理
            for(int i = 0; i < targetNums; i++){
                // 4.1 初始化每个目标代理的控制器
                AID nickname = new AID("targetAgent_" + i, AID.ISLOCALNAME);
                // 4.1.1 随机找到坐标处于[range,height-range-1],y坐标处于[range,width-range-1]的坐标点
                int x = random.nextInt(height-2*range) + range;
                int y = random.nextInt(width-2*range) + range;
                Position newPos = new Position(x, y);
                // 4.1.2 确保任意两个目标点没有重合信号，如果随机生成的点不在已生成目标点的范围内，并且不是障碍物的位置，则生成该目标点
                if(!AppUtils.inTargetRange(newPos, Data.targetPositions.values(), range) && ShowGui.board[x][y] != Data.OBSTACLE_SIGNAL){
                    // 如果不冲突
                    Data.targetPositions.put(nickname, newPos);
                }else{
                    // 如果冲突，重新生成新坐标
                    i--;
                    continue;
                }

                // 4.1.2 将代理位置和影响范围存在Object数组，传给每个目标代理
                Object[] message = {newPos, range};
                AgentController targetController = Data.targetContainer.createNewAgent(nickname.getLocalName(), TargetAgent.class.getName(),message);
                // 4.2 将目标代理的名称和控制器放入targetControllers中
                Data.targetControllers.put(nickname, targetController);
                targetController.start();
            }

            DirectTA directTA = new DirectTA();

            List<Task> tasks = TaskContainer.createTaskInstance(DetectEmit.class.getName(), targetNums);

            directTA.TaskAssign(Data.targetAgents, tasks);


            // 5. 主容器初始化管理员代理
            AgentController scheduleController = Data.scheduleContainer.createNewAgent("Admin", Schedule.class.getName(), null);
            scheduleController.start();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}
